package com.fly.show.docker;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.file.Paths;
import java.util.Arrays;

import javax.annotation.PostConstruct;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.fly.core.entity.JsonResult;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.spotify.docker.client.DefaultDockerClient;
import com.spotify.docker.client.DockerCertificates;
import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.exceptions.DockerCertificateException;
import com.spotify.docker.client.exceptions.DockerException;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@Api(tags = "Docker配置")
@RequestMapping("/dockerServer")
public class DockerServerController
{
    @Autowired
    DockerService dockerService;
    
    @ApiOperation("001-注册")
    @ApiOperationSupport(order = 10)
    @ApiImplicitParam(name = "url", value = "docker服务地址", required = true)
    @PostMapping("/envInit")
    public JsonResult<?> envInit(String url, MultipartFile ca, MultipartFile cert, MultipartFile key)
    {
        if (StringUtils.isBlank(url) || ca == null || cert == null || key == null)
        {
            return JsonResult.error("docker服务地址、ca证书、客户端证书或客户端私钥不能为空");
        }
        try
        {
            String subDir = "/docker_ca/" + StringUtils.trimToEmpty(url).replace(":", "_");
            try (InputStream is = ca.getInputStream())
            {
                FileUtils.copyInputStreamToFile(is, new File(subDir, "ca.pem"));
            }
            try (InputStream is = cert.getInputStream())
            {
                FileUtils.copyInputStreamToFile(is, new File(subDir, "cert.pem"));
            }
            try (InputStream is = key.getInputStream())
            {
                FileUtils.copyInputStreamToFile(is, new File(subDir, "key.pem"));
            }
            // 启用TLS
            DockerClient dockerclient = DefaultDockerClient.builder().uri(URI.create("https://" + url)).dockerCertificates(new DockerCertificates(Paths.get(subDir))).build();
            if (StringUtils.equals(dockerclient.ping(), "OK"))
            {
                dockerService.add(dockerclient);
                return JsonResult.success("初始化合作方docker成功");
            }
        }
        catch (IllegalStateException | IOException | DockerException | InterruptedException | DockerCertificateException e)
        {
            log.error(e.getMessage());
            return JsonResult.error("初始化出错，请检查docker服务地址、ca证书、客户端证书或客户端私钥是否合法");
        }
        return JsonResult.error("初始化合作方docker出错");
    }
    
    @ApiOperation("002-资源池")
    @ApiOperationSupport(order = 20)
    @GetMapping("/clients")
    public JsonResult<?> clients()
    {
        return JsonResult.success(dockerService.getClients(), "处理成功！");
    }
    
    /**
     * 遍历docker_ca目录
     * 
     * @see [类、类#方法、类#成员]
     */
    @PostConstruct
    private void initDockers()
    {
        try
        {
            Arrays.stream(new File("/docker_ca").listFiles()).filter(File::isDirectory).map(File::getAbsolutePath).forEach(path -> initDocker(path));
        }
        catch (Exception e)
        {
            log.error(e.getMessage());
        }
    }
    
    /**
     * 初始化DockerClient
     * 
     * @param path
     * @see [类、类#方法、类#成员]
     */
    private void initDocker(String path)
    {
        try
        {
            String url = new File(path).getName().replace("_", ":");
            log.info("###### will init docker for {} by {}", url, path);
            DockerClient dockerclient = DefaultDockerClient.builder().uri(URI.create("https://" + url)).dockerCertificates(new DockerCertificates(Paths.get(path))).build();
            if (StringUtils.equals(dockerclient.ping(), "OK"))
            {
                dockerService.add(dockerclient);
            }
        }
        catch (DockerCertificateException | DockerException | InterruptedException e)
        {
            log.error(e.getMessage());
        }
    }
}
